package com.iakuil.app.common.core.util;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 自旋锁
 *
 * @author Kai
 */
@Slf4j
@UtilityClass
public class SpinLockUtils {

    private static AtomicReference<Object> SIGN = new AtomicReference<>();

    /**
     * 自旋锁加锁
     *
     * @param obj           加锁对象
     * @param reentrantFlag 是否可重入
     */
    public static <T> void lock(T obj, boolean reentrantFlag) {
        // 若可重入标志为true，且若尝试加锁的对象和已加的锁中的对象相同，可重入，并加锁成功
        if (reentrantFlag && obj == SIGN.get()) {
            return;
        }
        // If the lock is not acquired, it can be spun through CAS
        while (!SIGN.compareAndSet(null, obj)) {
            // do nothing
            log.info("休息一会~");
        }
    }

    /**
     * 自旋锁解锁
     *
     * @param obj 解锁对象
     */
    public static <T> void unlock(T obj) {
        // 锁的线程和目前的线程相等时，才允许释放锁
        if (obj == SIGN.get()) {
            SIGN.compareAndSet(obj, null);
        }
    }
}
